package com.sff.site.tree {
	
	import com.sff.core.sff_internal;
	import com.sff.site.core.INode;
	import com.sff.site.node.Node;
	import com.sff.site.tree.SiteTree;
	
	import flash.utils.Dictionary;	

	public class TreesProviderClass {
		
		sff_internal static var MAIN_DEVICE : String;
		
		public function TreesProviderClass( ) {
			if( instance != null ) throw new Error( "TreesProvider est deja instancié" );
			_trees = new Array( );
			_treesMap = new Dictionary();
		}
		
		sff_internal function parseSiteMap(siteMap:XML) : Tree {
			
			var treeDescriptor : TreeDescriptor = new TreeDescriptor( siteMap );			
			sff_internal::injectTreeDescription( treeDescriptor );
			
			return sff_internal::getSubTree( treeDescriptor );
		}
		
		
		/**
		 * add a tree description to the SiteTree. this method return false if the SiteTree contain no compatible data
		 * at the description path.
		 */
		sff_internal function injectTreeDescription( descriptor : TreeDescriptor ) : Boolean {
			
			var tree : SiteTree = sff_internal::getTree( descriptor.path.getDevice() );
			var target : INode = descriptor.path.toNode( );
			if( descriptor.defaultId ) {
				( target as TreeNode ).sff_internal::setDefaultId( descriptor.defaultId );
			}	
			tree.sff_internal::buildTreeNode( descriptor, target );
			return true;
		}
		
		/**
		 * return the tree corresponding to the descriptor.
		 * Descriptor is build by a manifest in order fill the SiteTree and 
		 * to provide to module the part of the site tree corresponding to descriptor
		 * 
		 * @throws 
		 */
		sff_internal function getSubTree( descriptor : TreeDescriptor ) : Tree {
			use namespace sff_internal;
			var root : TreeNode = descriptor.path.toNode( ) as TreeNode;
			var node : Node = root.createNode( null );
			var tree : Tree = new Tree( node );
			tree.buildTreeNode( descriptor, node );
			
			return tree;
		}
		
		
		sff_internal function getTree( device : String = "" ) : SiteTree {
			if( device == null || device == "" ) device = sff_internal::MAIN_DEVICE;
			var t : SiteTree = _treesMap[ device ];
			if( !t ) throw new Error( "TreesProvider - getTree : no tree with the given device '" + device + "'" );
			return t;
		}

		sff_internal function hasTree( device : String ) : Boolean {
			return ( _treesMap[ device ] != undefined );
		}

		sff_internal function createTree( device : String ) : SiteTree {
			
			if( sff_internal::hasTree( device ) ) return sff_internal::getTree( device );
			
			var t : SiteTree = new SiteTree( device );
			_trees.push( t );
			_treesMap[ device ] = t;
			t.root.activate();
			return t;
		}
		
		public function toString() : String {
			var str : String = "TreeProvider : </br>";
			for each (var t : INode in _trees) {
				str += t.stringify( 1 );
			}
			return str;
		}
		
		

		private var _trees : Array;		
		private var _treesMap : Dictionary;
		public static var instance : TreesProviderClass;
		
		public static function start( ) : TreesProviderClass {
			if (instance == null)
				instance = new TreesProviderClass();
			return instance;
		}
		
	}
}
